#ifndef NET_RPC_RPC_SERVICE_H
#define NET_RPC_RPC_SERVICE_H

#include <ext/hash_map>
// Google protobuff
#include "google/protobuf/service.h"

#include "base/mutex.h"
#include "net/rpc/rpc.h"
#include "net/base/connection.h"
#include "io/byte_stream.h"

using __gnu_cxx::hash_map;

class Executor;
class RpcMessageHeader;

namespace google {
namespace protobuf {
class Message;
class Service;
}
}
struct ClientContext {
  ClientContext();
  ByteStream read_buf;
  Mutex mutex;
  bool disconnected_;
};

class RpcService : public ServerConnection {
 public:
  RpcService(int port, Executor* executor);
  virtual void HandleRead(int sockfd, char* buffer, int size);
  void HandleReadInternal(int sockfd, char* buffer, int size);
  virtual void HandleConnect(int fd);
  virtual void HandleDisconnect(int fd);
  void ExportService(google::protobuf::Service* service);

 protected:
  void RpcDoneClosure(int fd, RpcMessageHeader* header,
      google::protobuf::Message* resp_pb);
  void Process(const string& name, const string& request,
               string* response, RPC* rpc);
  ClientContext* GetClientContext(int sfd);

 private:
  void ClearDisconnected();
  hash_map<int, ClientContext*> client_context_;
  hash_map<int, ClientContext*> disconnected_client_context_;
  Mutex client_context_mutex_;
  google::protobuf::Service* service_;
  Executor* executor_;
};

#endif
